package com.qls.mt.biz.order.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.qls.ali.api.AliRemoteService;
import com.qls.core.ali.order.bookrq.request.BookRq;
import com.qls.core.ali.order.bookrq.request.OrderGuest;
import com.qls.core.ali.order.cancelrq.CancelRq;
import com.qls.core.ali.order.common.DailyInfo;
import com.qls.core.ali.order.validaterq.request.ValidateRq;
import com.qls.core.constant.Constant;
import com.qls.core.dto.HtDailyRoom;
import com.qls.core.entity.DtOrderChannels;
import com.qls.core.utils.R;
import com.qls.mt.biz.common.service.DtOrderChannelsService;
import com.qls.mt.biz.common.utils.FxBaseApiRequest;
import com.qls.mt.biz.common.utils.MtClient;
import com.qls.mt.biz.order.service.MtOrderService;
import com.qls.mt.module.dto.book.request.MtBook;
import com.qls.mt.module.dto.book.response.MtBookResult;
import com.qls.mt.module.dto.cancel.CancelRequest;
import com.qls.mt.module.dto.cancel.CancelResponse;
import com.qls.mt.module.dto.check.PriceModels;
import com.qls.mt.module.dto.check.request.Check;
import com.qls.mt.module.dto.check.response.CheckResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author doyoung
 */
@Slf4j
@Service("mtOrderService")
public class MtOrderServiceImpl implements MtOrderService {

    @Autowired
    private DtOrderChannelsService dtOrderChannelsService;

    @Autowired
    private AliRemoteService aliRemoteService;

    /**
     * 下单前校验(美团）
     *
     * @param validateRq
     * @return
     */
    @Override
    public R validate(ValidateRq validateRq) {
        Long hotelId = Long.valueOf(validateRq.getHotelId());
        Long rpCode = Long.valueOf(validateRq.getRatePlanCode());
        String method = "hotel.order.check";
        Check checkRequest = new Check();
        checkRequest.setHotelId(Long.valueOf(validateRq.getHotelId()));
        checkRequest.setGoodsId(rpCode);
        checkRequest.setCheckinDate(validateRq.getCheckIn());
        checkRequest.setCheckoutDate(validateRq.getCheckOut());
        checkRequest.setRoomNum(Integer.valueOf(validateRq.getRoomNum()));

        Map<String, Integer> stringIntegerMap = calculatePrice(validateRq.getDailyInfos(), Integer.valueOf(validateRq.getRoomNum()));
        checkRequest.setTotalPrice(stringIntegerMap.get("totaolPrice"));

        FxBaseApiRequest fxBaseApiRequest = new FxBaseApiRequest();
        fxBaseApiRequest.setData(JSONObject.toJSONString(checkRequest));
        String userName = validateRq.getAuthenticationToken().getUsername();

        // 查询下单渠道 （修改）
        DtOrderChannels dtOrderChannels = dtOrderChannelsService.queryByHotelId(hotelId);
        if (dtOrderChannels != null) {
            fxBaseApiRequest.setAccesskey(dtOrderChannels.getAccessKey());
            fxBaseApiRequest.setSecretKey(dtOrderChannels.getSecret());
            fxBaseApiRequest.setPartnerId(dtOrderChannels.getPartnerId());
        } else {
            log.error("美团：请配置飞猪接口用户名为{}的店铺对应的美团渠道账号", userName);
        }
        fxBaseApiRequest.setMethod(method);
        log.info("美团：下单前校验,酒店ID：{},房型ID：{},RP:{},请求报文:{}", validateRq.getHotelId(), validateRq.getRoomTypeId(), validateRq.getRatePlanCode(), fxBaseApiRequest.getData());
        String mtResult = "";
        try {
            mtResult = new MtClient().post(fxBaseApiRequest);
        } catch (Exception ex) {
            log.error("美团：下单前校验异常,酒店ID：{},房型ID：{},RP:{},异常信息:{}", validateRq.getHotelId(), validateRq.getRoomTypeId(), validateRq.getRatePlanCode(), ex.toString());
        }
        log.info("美团：下单前校验,酒店ID：{},房型ID：{},RP:{},返回报文:{}", validateRq.getHotelId(), validateRq.getRoomTypeId(), validateRq.getRatePlanCode(), mtResult);
        JSONObject jsonObject = JSONObject.parseObject(mtResult);
        String result = jsonObject.getString("result");
        CheckResult checkResponse = JSONObject.parseObject(result, CheckResult.class);

        List<HtDailyRoom> updateDailyRoom = new ArrayList<>();
        //校验成功
        log.info("美团验单结果：{}", result);
        if (checkResponse.getCode() == 0 || checkResponse.getCode() == 8) {
            List<PriceModels> priceModelsList = checkResponse.getPriceModels();
            for (PriceModels priceModels : priceModelsList) {
                HtDailyRoom htDailyRoom = new HtDailyRoom();
                htDailyRoom.setSubPrice(priceModels.getSubPrice());
                htDailyRoom.setDate(priceModels.getDate());
                htDailyRoom.setPrice(priceModels.getSalePrice());
                htDailyRoom.setRpCode(rpCode.toString());
                updateDailyRoom.add(htDailyRoom);
            }
        } else {
            return R.error();
        }
        log.info("店铺：{}，美团下单前校验，验单通过，酒店id：{}，RP：{}",
                validateRq.getCustomerNumber(), validateRq.getHotelId(), rpCode);
        return R.ok().put("data", updateDailyRoom);
    }


    /**
     * 预约下单(美团）
     *
     * @param bookRq BookRq
     * @return
     */
    @Override
    public R book(BookRq bookRq) {
        String method = "hotel.order.booking";
        String hotelId = bookRq.getHotelId();
        String userName = bookRq.getAuthenticationToken().getUsername();
        DtOrderChannels dtOrderChannels = dtOrderChannelsService.queryByHotelId(Long.valueOf(hotelId));
        String accessKey = "";
        String secretKey = "";
        Integer partnerId = 0;
        if (dtOrderChannels != null) {
            accessKey = dtOrderChannels.getAccessKey();
            secretKey = dtOrderChannels.getSecret();
            partnerId = dtOrderChannels.getPartnerId();
        } else {
            log.error("美团：请配置飞猪接口用户名为{}的店铺对应的美团渠道账号", userName);
        }
        MtBook mtBook = new MtBook();
        mtBook.setHotelId(Long.valueOf(bookRq.getHotelId()));
        mtBook.setGoodsId(Long.valueOf(bookRq.getRatePlanCode()));
        StringBuilder personNames = new StringBuilder();
        for (OrderGuest guest : bookRq.getOrderGuests()) {
            personNames.append(guest.getName()).append(",");
        }
        personNames = new StringBuilder(personNames.toString().replaceAll("\\,$", ""));
        mtBook.setPersonNames(personNames.toString());
        mtBook.setContactName(bookRq.getContactName());
        mtBook.setContactPhone(bookRq.getContactTel());
        mtBook.setArriveDate(bookRq.getLatestArriveTime());
        mtBook.setCheckinDate(bookRq.getCheckIn());
        mtBook.setCheckoutDate(bookRq.getCheckOut());
        mtBook.setRoomNum(Integer.valueOf(bookRq.getRoomNum()));
        //订单总价，单位为分。总价=预订房间数x预定日期内房间单价。
        // 例如，4月1日入住，4月3日离店，预定2间房，则总价=2*(4月1日房价+4月2日房价）
        Map<String, Integer> priceMap = this.calculatePrice(bookRq.getDailyInfos(), Integer.valueOf(bookRq.getRoomNum()));
        mtBook.setTotalPrice(priceMap.get("totaolPrice"));
        mtBook.setSettlePrice(priceMap.get("settlePrice"));
        mtBook.setDistributorOrderId(bookRq.getTaoBaoOrderId());
        //设置发票信息，目前都是酒店前台开票,不需要美团开票
        mtBook.setNeedInvoice(0);
        FxBaseApiRequest fxBaseApiRequest = new FxBaseApiRequest();
        fxBaseApiRequest.setAccesskey(accessKey);
        fxBaseApiRequest.setSecretKey(secretKey);
        fxBaseApiRequest.setPartnerId(partnerId);
        fxBaseApiRequest.setData(JSONObject.toJSONString(mtBook));
        fxBaseApiRequest.setMethod(method);


        log.info("美团：预约下单，订单号：{},请求报文：{}", bookRq.getTaoBaoOrderId(), fxBaseApiRequest.getData());
        int max = 3;
        int count = 0;
        MtBookResult mtBookResult = null;
        while (count <= max) {
            try {
                String res = new MtClient().post(fxBaseApiRequest);
                System.out.println(res);
                mtBookResult = JSONObject.parseObject(res, MtBookResult.class);
            } catch (Exception ex) {
                log.error("美团：订单号：{}，错误信息：{}", bookRq.getTaoBaoOrderId(), ex.toString());
            }
            if (Objects.isNull(mtBookResult) || mtBookResult.getCode() == 1) {
                count++;
            } else {
                log.warn("美团：预约下单，订单号：{},返回报文：{}", bookRq.getTaoBaoOrderId(), mtBookResult);
                if (mtBookResult.getCode() == 4 || mtBookResult.getCode() == 10) {
                    return R.error(-1, "产品已售完，扣减库存失败或产品被拉黑, 不允许购买");
                }
                if (mtBookResult.getCode() == 0 || mtBookResult.getCode() == 2) {
                    log.info("美团保存订单成功，订单id：{}", mtBookResult.getResult().getMtOrderId());
                    R r = R.ok().put("buyOrderId", mtBookResult.getResult().getMtOrderId());
                    System.out.println(r);
                    return r;
                } else {
                    log.error("美团：预约下单失败，订单号：{}，错误信息:{}", bookRq.getTaoBaoOrderId(), mtBookResult.getMessage());
                    return R.error();
                }
            }
        }
        return R.error();
    }

    /**
     * 取消订单
     *
     * @param cancelRq
     * @return
     */
    @Override
    public R cancel(CancelRq cancelRq) {
        Long hotelId = Long.valueOf(cancelRq.getHotelId());
        String method = "hotel.order.cancel";
        DtOrderChannels dtOrderChannelsEntity = dtOrderChannelsService.queryByHotelId(hotelId);
        String accessKey = "";
        String secretKey = "";
        Integer partId = 0;
        if (dtOrderChannelsEntity != null) {
            accessKey = dtOrderChannelsEntity.getAccessKey();
            secretKey = dtOrderChannelsEntity.getSecret();
            partId = dtOrderChannelsEntity.getPartnerId();
        } else {
            log.error("美团：请配置飞猪接口用户名为{}的店铺对应的美团渠道账号", cancelRq.getAuthenticationToken().getUsername());
        }
        CancelRequest cancelRequest = new CancelRequest();
        cancelRequest.setDistributorOrderId(cancelRq.getTaoBaoOrderId());
        cancelRequest.setMtOrderId(Long.valueOf(cancelRq.getBuyOrderCode()));
        cancelRequest.setCancelReason("正常取消");
        cancelRequest.setCancelCheck(0);


        FxBaseApiRequest fxBaseApiRequest = new FxBaseApiRequest();
        fxBaseApiRequest.setAccesskey(accessKey);
        fxBaseApiRequest.setSecretKey(secretKey);
        fxBaseApiRequest.setPartnerId(partId);
        fxBaseApiRequest.setMethod(method);
        fxBaseApiRequest.setData(JSONObject.toJSONString(cancelRequest));
        String cancelResult = "";
        log.info("美团：取消订单，订单号：{},请求报文：{}", cancelRq.getTaoBaoOrderId(), fxBaseApiRequest.getData());
        try {
            cancelResult = new MtClient().post(fxBaseApiRequest);
        } catch (Exception ex) {
            log.error("美团：取消订单失败，订单号：{}，错误信息:{}", cancelRq.getTaoBaoOrderId(), ex.toString());
        }
        log.info("美团：取消订单，订单号：{},返回报文：{}", cancelRq.getTaoBaoOrderId(), cancelResult);
        CancelResponse cancelResponse = JSONObject.parseObject(cancelResult, CancelResponse.class);
        //成功取消
        if (cancelResponse.getCode() == 0) {
            return R.ok();
        } else if (cancelResponse.getCode() == 5) {
            return R.ok(1);
        }
        return R.error();
    }

    /**
     * 订单状态变更通知
     *
     * @param jsonObject
     * @return
     */
    @Override
    public R callback(JSONObject jsonObject) {
        //21 预订成功 book_suc
        //22 预订失败 book_fail
        //31 取消成功 cancel_suc
        //50 已入住 book_checkin
        //40 美团客服介入退款 abort
        if (jsonObject == null || StringUtils.isBlank(jsonObject.getString("distributorOrderId"))) {
            return R.error();
        }
        JSONObject json = new JSONObject();
        json.put("buyOrderId", jsonObject.getString("mtOrderId"));
        R r;
        Constant.MtOrderStatus mtOrderStatus = Constant.MtOrderStatus.getStatusByValue(jsonObject.getInteger("orderStatus"));
        switch (mtOrderStatus) {
            case book_suc:
                log.info("预订成功:{}", jsonObject);
                json.put("code", 0);
                r = aliRemoteService.callback(json);
                log.info("飞猪返回:{}", r);
                break;
            case book_fail:
                log.info("预订失败:{}", jsonObject);
                json.put("code", -1);
                r = aliRemoteService.callback(json);
                log.info("飞猪返回:{}", r);
                break;
            case cancel_suc:
                log.info("取消成功:{}", jsonObject);
                json.put("code", 1);
                r = aliRemoteService.callback(json);
                log.info("飞猪返回:{}", r);
                break;
            case abort:
                log.info("已入住:{}", jsonObject);
                json.put("code", 2);
                r = aliRemoteService.callback(json);
                log.info("飞猪返回:{}", r);
                break;
            case book_checkin:
                log.info("美团客服介入退款:{}", jsonObject);
                json.put("code", 3);
                r = aliRemoteService.callback(json);
                log.info("飞猪返回:{}", r);
                break;
            default:
                break;
        }
        return R.ok();
    }

    /**
     * 计算价格
     *
     * @return
     */
    private Map<String, Integer> calculatePrice(List<DailyInfo> dailyInfos, Integer roomNum) {
        // 一间房总价
        int totaolPriceOne = 0;

        // 佣金
        int subPrice = 0;
        Map<String, Integer> map = new HashMap<>();
        for (DailyInfo d : dailyInfos) {
            totaolPriceOne += d.getPrice();
            subPrice += d.getSubPrice();
        }
        // 预定所有房间 所有间夜的总价
        int totaolPrice = totaolPriceOne * roomNum;
        // 预定所有房间 所有间夜下单价
        int settlePrice = (totaolPriceOne - subPrice) * roomNum;
        map.put("totaolPrice", totaolPrice);
        map.put("settlePrice", settlePrice);
        return map;
    }

}
